﻿using System;
using System.ComponentModel;
using Zive.Color;

namespace LabColorPicker {

    public class ColorData: INotifyPropertyChanged {

        public ColorData( ) {
            _xyzColor = new XyzColor( );
            _rgbColor = new RgbColor( );
            _labColor = new LabColor( );
            _hslColor = new HslColor( );

            _HookPropertyChangedEvents( );
        }

        public ColorData( ColorData orig ) {
            _xyzColor = new XyzColor( orig._xyzColor );
            _rgbColor = new RgbColor( orig._rgbColor );
            _labColor = new LabColor( orig._labColor );
            _hslColor = new HslColor( orig._hslColor );
            _isSet = true;

            _HookPropertyChangedEvents( );
        }

        private XyzColor _xyzColor;
        public XyzColor Xyz {
            get { return _xyzColor; }
            set { _Update( value ); }
        }

        private RgbColor _rgbColor;
        public RgbColor Rgb {
            get { return _rgbColor; }
            set { _Update( value ); }
        }

        private LabColor _labColor;
        public LabColor Lab {
            get { return _labColor; }
            set { _Update( value ); }
        }

        private HslColor _hslColor;
        public HslColor Hsl {
            get { return _hslColor; }
            set { _Update( value ); }
        }

        private bool _isSet;
        public bool IsSet {
            get { return _isSet; }
        }

        public void Set( ColorData src ) {
            if ( null == src ) {
                throw new ArgumentNullException( "src" );
            }

            _UnhookPropertyChangedEvents( );

            _xyzColor = new XyzColor( src._xyzColor );
            _rgbColor = new RgbColor( src._rgbColor );
            _labColor = new LabColor( src._labColor );
            _hslColor = new HslColor( src._hslColor );
            _isSet = src._isSet;

            _HookPropertyChangedEvents( );

            _OnPropertyChanged( "Xyz" );
            _OnPropertyChanged( "Lab" );
            _OnPropertyChanged( "Rgb" );
            _OnPropertyChanged( "Hsl" );
        }

        private void XyzColor_PropertyChanged( object sender, PropertyChangedEventArgs ev ) {
            _Update( _xyzColor );
        }

        private void RgbColor_PropertyChanged( object sender, PropertyChangedEventArgs ev ) {
            _Update( _rgbColor );
        }

        private void LabColor_PropertyChanged( object sender, PropertyChangedEventArgs ev ) {
            _Update( _labColor );
        }

        private void HslColor_PropertyChanged( object sender, PropertyChangedEventArgs ev ) {
            _Update( _hslColor );
        }

        private void _HookPropertyChangedEvents( ) {
            if ( null != _xyzColor ) {
                _xyzColor.PropertyChanged += XyzColor_PropertyChanged;
            }
            if ( null != _labColor ) {
                _labColor.PropertyChanged += LabColor_PropertyChanged;
            }
            if ( null != _rgbColor ) {
                _rgbColor.PropertyChanged += RgbColor_PropertyChanged;
            }
            if ( null != _hslColor ) {
                _hslColor.PropertyChanged += HslColor_PropertyChanged;
            }
        }

        private void _UnhookPropertyChangedEvents( ) {
            if ( null != _xyzColor ) {
                _xyzColor.PropertyChanged -= XyzColor_PropertyChanged;
            }
            if ( null != _labColor ) {
                _labColor.PropertyChanged -= LabColor_PropertyChanged;
            }
            if ( null != _rgbColor ) {
                _rgbColor.PropertyChanged -= RgbColor_PropertyChanged;
            }
            if ( null != _hslColor ) {
                _hslColor.PropertyChanged -= HslColor_PropertyChanged;
            }
        }

        private void _Update( RgbColor value ) {
            _UnhookPropertyChangedEvents( );

            _rgbColor = new RgbColor( value );
            _xyzColor = RgbColorConverter.Convert( _rgbColor );
            _labColor = LabColorConverter.Convert( _xyzColor );
            _hslColor = HslColorConverter.Convert( _xyzColor );
            _isSet = true;

            _HookPropertyChangedEvents( );

            _OnPropertyChanged( "Xyz" );
            _OnPropertyChanged( "Lab" );
            _OnPropertyChanged( "Rgb" );
            _OnPropertyChanged( "Hsl" );
        }

        private void _Update( LabColor value ) {
            _UnhookPropertyChangedEvents( );

            _labColor = new LabColor( value );
            _xyzColor = LabColorConverter.Convert( _labColor );
            _rgbColor = RgbColorConverter.Convert( _xyzColor );
            _hslColor = HslColorConverter.Convert( _xyzColor );
            _isSet = true;

            _HookPropertyChangedEvents( );

            _OnPropertyChanged( "Xyz" );
            _OnPropertyChanged( "Lab" );
            _OnPropertyChanged( "Rgb" );
            _OnPropertyChanged( "Hsl" );
        }

        private void _Update( XyzColor value ) {
            _UnhookPropertyChangedEvents( );

            _xyzColor = new XyzColor( value );
            _labColor = LabColorConverter.Convert( _xyzColor );
            _rgbColor = RgbColorConverter.Convert( _xyzColor );
            _hslColor = HslColorConverter.Convert( _xyzColor );
            _isSet = true;

            _HookPropertyChangedEvents( );

            _OnPropertyChanged( "Xyz" );
            _OnPropertyChanged( "Lab" );
            _OnPropertyChanged( "Rgb" );
            _OnPropertyChanged( "Hsl" );
        }

        private void _Update( HslColor value ) {
            _UnhookPropertyChangedEvents( );

            _hslColor = new HslColor( value );
            _xyzColor = HslColorConverter.Convert( _hslColor );
            _labColor = LabColorConverter.Convert( _xyzColor );
            _rgbColor = RgbColorConverter.Convert( _xyzColor );
            _isSet = true;

            _HookPropertyChangedEvents( );

            _OnPropertyChanged( "Xyz" );
            _OnPropertyChanged( "Lab" );
            _OnPropertyChanged( "Rgb" );
            _OnPropertyChanged( "Hsl" );
        }

        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;
        private void _OnPropertyChanged( string propertyName ) {
            var handlers = PropertyChanged;
            if ( null != handlers ) {
                handlers( this, new PropertyChangedEventArgs( propertyName ) );
            }
        }

        #endregion

    }

}
